package com.smartmail.receiving;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.smartmail.accounts.MailAccount;
import com.smartmail.mailing.MailMessage;
import com.smartmail.receiving.imap.IMAPSynchronizeTask;
import com.smartmail.receiving.pop3.POP3DownloadMsgsTask;
import com.smartmail.receiving.pop3.POP3MailBoxCheckTask;

/**
 * Class containing the implementation of methods (requests) to perform at mailbox.
 * 
 * @author Tomek
 *
 */
public class ReceivingRequestsHandler {
	
	
	/**
	 * Initialize handler.
	 * 
	 * @param context - application context
	 */
	public static void init(Context context){
		
		_context = context;
	}

	/**
	 * Try to fully download message from server to device memory.
	 * This methods is only useful for POP3 protocol.
	 * (In IMAP all messages are automically partly-downloaded)
	 * 
	 * @param message - MailMessage object which identifies message in server.
	 * @param account - MailAccount from which inbox message will be downloaded.
	 * @return - true on success, otherwise false.
	 */
	public static boolean downloadOnDemand(MailMessage message , MailAccount account){

		switch( account.getIncomingMailServerProtocolType()){
		
			/**
			 * IMAP support not yet supported
			 */
			case IMAP:{
				
				Log.d(_logTag,
						"ReceivingRequestHandler : in IMAP protocol downloadOnDemand is unsupported - "
				+ account.getVisibleName());
				
				return false;
			}
			/**
			 * POP3 retrieval protocol support
			 */
			case POP3:{
				
				/**
				 * in case of error while retrieving for retrieval thread
				 */
				AbstractRetrievalThread thread = RetrievalService.getRetrievalThread(account);
				if(thread == null ){
					
					Log.d(_logTag, "ReceivingRequestHandler : no retrieval thread available - " + account.getMailAddress());
					return false;
				}
				
				/**
				 * add this message to queue of messages to download
				 */
				List<MailMessage> list = thread.getMessagesToDownload();
				if( !list.contains(message))
					list.add(message);
				
				/**
				 * schedule task of downloading message to device
				 */
				thread.downloadMessages();
				//thread.getExecutor().schedule(new POP3DownloadMsgsTask(account , _context), 0, TimeUnit.MILLISECONDS);
				Log.d(_logTag,"ReceivingRequestHandler : scheduled new download task - " + account.getMailAddress());
				
				break;
			}
		
		}
		
		return true;
	}
	
	/**
	 * Delete message from device. It consist deleting message from internal phone memory,
	 * and deleting message from incoming database, and also sending intent about 
	 * message removal.
	 * 
	 * @param mailAccount - mail account to which deleted messages belongs
	 * @param mailMessage - mail message object which identifies messages to delete
	 * @return
	 */
	public static boolean deleteMessageFromDevice(MailAccount mailAccount, MailMessage mailMessage){
		
		IncomingMailDBManager manager = Receiving.getDBManager(mailAccount);
		
		// first -  try to delete message from database
		boolean dbResult = manager.deleteMessage(mailMessage.getMessageHash());
		
		if( !dbResult) 
			return false;
		
		
		//secondly - delete message from device
		InternalStorageUtility.deleteMessageFromSDCard(mailMessage);
		
		//third -  send intent to AccountMsgActivity
		Intent intent = new Intent(Receiving.MESSAGE_DELETED_INTENT);
		intent.putExtra(Receiving.MAIL_INFO_ACCOUNT_ID, mailAccount.getAccountID());
		intent.putExtra(Receiving.MAIL_INFO_HASH, mailMessage.getMessageHash());
		_context.sendBroadcast(intent);
		
		
		return true;
	}
	
	/**
	 * Delete message from server. This method does not remove messages from the server immediately,
	 * but stores the message in the list of messages to delete.
	 *  The message is deleted the next time you check your mailbox.
	 *  
	 * @param mailAccount - mail account to which deleted messages belongs
	 * @param mailMessage - mail message object which identifies messages to delete
	 * @return - true on success, otherwise false
	 */
	public static boolean deleteMessageFromServer(MailAccount mailAccount, MailMessage mailMessage){
		
		IncomingMailDBManager manager = Receiving.getDBManager(mailAccount);
		
		boolean result = manager.addMessageToDeleteFromServer(mailMessage);
		return result;
	}
	
	/**
	 * Check mailbox for this account in search of new incomimg messages.
	 * 
	 * @param account - mail account to which identifes mailbox to be checked
	 */
	public static void checkMailBoxOnDemand(MailAccount account){
		
		
		switch( account.getIncomingMailServerProtocolType()){
		
			/**
			 * imap support not yet supported
			 */
			case IMAP:{
				
				//Log.d(_logTag,"check mailbox imap");
				
				/**
				 * in case of error while retrieving for retrieval thread
				 */
				AbstractRetrievalThread thread = RetrievalService.getRetrievalThread(account);
				if(thread == null){
					
					Log.d(_logTag, "ReceivingRequestHandler : no  retrieval thread available - " 
					+ account.getMailAddress());
					return;
				}
				thread.checkMailbox();
				//thread.getExecutor().schedule(new IMAPSynchronizeTask(account,_context), 0, TimeUnit.SECONDS);
				
				break;

			}
			/**
			 * POP3 retrieval protocol support
			 */
			case POP3:{

				/**
				 * in case of error while retrieving for retrieval thread
				 */
				AbstractRetrievalThread thread = RetrievalService.getRetrievalThread(account);
				if(thread == null){
					
					Log.d(_logTag, "Receiving : no  retrieval thread available");
					return;
				}
				thread.checkMailbox();
				//thread.getExecutor().schedule(new POP3MailBoxCheckTask(account,_context), 0, TimeUnit.MILLISECONDS);
				
				break;
			}
	
		}
	
	}
	
	/**
	 * Returns Date object of last mailbox of this MailAccount checking.
	 * I assume that date of last inbox folder checking is the same as
	 * date of last received message.
	 * 
	 * @param mailAccount - mail account to which identifies mailbox
	 * @return - last INBOX checking date
	 */
	public static Date getLastInBoxCheckingDate(MailAccount mailAccount){
		
		IncomingMailDBManager manager = Receiving.getDBManager(mailAccount);
		
		//get last received email
		MailMessage lastMessage = manager.getLastMail();
		
		Date lastDate;
		
		if(lastMessage == null || lastMessage.getSentDate() == null)
			lastDate = new Date(0L);
		else
			lastDate =  lastMessage.getSentDate();
		
		return lastDate;
		
		
	}
	
	/**
	 * This methods returns list of Mail Messages which are wanted to be downloaded.
	 * @param accountID - mail account ID which identifies mailbox
	 * @return - ist of Mail Messages which are wanted to be downloaded from this mailbox.
	 */
	public static List<MailMessage> getMessagesToDownload(Integer accountID) {

		AbstractRetrievalThread thread = null;
		
		if( (thread = RetrievalService.getRetrievalThread(accountID)) == null  )
			return null;
		
		else
			return thread.getMessagesToDownload();
	}
	
	/**
	 * Set state of this message in database.
	 * 
	 * @param account - Mail Account object which identifies mail account
	 * @param message - message which state will be changed
	 * @param messageState - new state of Mail Message
	 * @return - true on success, false otherwise
	 */
	public static boolean setState(MailAccount account, MailMessage message, int messageState){
		
		IncomingMailDBManager manager = Receiving.getDBManager(account.getAccountID());
		message.setState(messageState);
		return manager.setState(messageState, message.getMessageHash());
	}
	
	/**
	 * log tag for logging purposes
	 */
	private static String _logTag = "com.smartmail.receiving";
	
	/**
	 * Application context
	 */
	private static Context _context;

}
